<template>
  <div
    class="action-block"
    ref="box"
    :style="{
      width: `${actionWidth}px`,
      left: `${actionLeft}px`,
      top: '10px',
      'background-color': `${color}`,
      // top: `${
      //   blockData
      //     ? blockData.top
      //       ? blockData.top + 'px'
      //       : defaultTop + 'px'
      //     : '0px'
      // }`,
    }"
  >
    <div class="action-box">
      <!--用于拉伸X 坐标，让他变长缩短-->
      <div
        class="left-box action"
        v-if="enableDragSide"
        @mousedown="onMouseLineDown($event, -1)"
        @contextmenu.prevent="() => {}"
      ></div>

      <!--时间块的具体内容 拖拽事件-->
      <div
        class="action-content"
        @mousedown="enableDragFree ? onMouseFreeDown($event) : null"
      >
        <slot></slot>
      </div>
      <!--用于拉伸X 坐标，让他变长缩短-->
      <div
        class="right-box action"
        v-if="enableDragSide"
        @mousedown="onMouseLineDown($event, 1)"
        @contextmenu.prevent="() => {}"
      ></div>
    </div>
  </div>
</template>

<script>
  import { EventBus, getAbsTop, getAbsLeft } from '../common/js/util'
  export default {
    name: 'action-block',
    props: {
      //时间块数据
      blockData: {
        type: Object,
        default: () => {},
      },
      // 行数据
      rowData: {
        type: Object,
        default: () => {},
      },
      // 所有数据
      ganttData: {
        type: Array,
        default: () => [],
      },
      //在外头选择的时间
      choiceTime: {
        type: Array,
        default: () => [],
      },
      //左右可拖拽
      enableDragSide: {
        type: Boolean,
        default: false,
      },
      //是否允许自由拖拽，但是该组件的自由拖拽不进行真实交互，只是回调事件
      enableDragFree: {
        type: Boolean,
        default: false,
      },
      //开始时间的字段
      startTimeCol: {
        type: String,
        default: 'startTime',
      },
      //结束时间的字段
      endTimeCol: {
        type: String,
        default: 'endTime',
      },
      //滚动条的距离
      scrollLeft: {
        type: Number,
        default: 0,
      },
      color: {
        type: String,
        default: '#ffedb3',
      },
    },
    computed: {
      //时间块的宽度
      actionWidth() {
        if (this.blockData) {
          const startTime = new Date(this.blockData[this.startTimeCol])

          const endTime = new Date(this.blockData[this.endTimeCol])

          //计算差值
          let diffTime = (endTime.getTime() - startTime.getTime()) / 1000 / 60
          return diffTime
        }
        return 0
      },
      //时间块的左边偏移量
      actionLeft() {
        if (this.blockData) {
          const limitTime = new Date(this.choiceTime[0])

          const startTime = new Date(this.blockData[this.startTimeCol])

          //计算时间块的左边距离甘特图边界的距离
          let diffTime = (startTime.getTime() - limitTime.getTime()) / 1000 / 60
          return diffTime
        }
        return 0
      },
    },
    data() {
      return {
        //默认的高度
        defaultTop: 10,
        mousePosition: {
          left: 0,
          right: 0,
        },
        uniqueId: 0,
      }
    },
    methods: {
      //时间块左右两边的可拖拽滑块 direction: -1 左边；1右边
      onMouseLineDown(e, direction) {
        const startTimeDate = new Date(this.blockData[this.startTimeCol])

        const endTimeDate = new Date(this.blockData[this.endTimeCol])

        let startTime = startTimeDate.getTime()
        let endTime = endTimeDate.getTime()

        //可滚动区域
        let wordDom = document.getElementById('ganttGrid')

        wordDom.onmousemove = (ee) => {
          // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
          let v = ee.clientX - e.clientX
          //v左边移动减少
          if (direction == -1) {
            //左边拉长是减少
            if (this.mousePosition.left < v) {
              //如果是缩短，那么就可以进行width不为-1的判断了
              if (this.actionWidth <= 0) {
                return
              }
            }

            //分钟赋值后，设置成new Date
            this.blockData[this.startTimeCol] = new Date(
              startTime + v * 1000 * 60
            ).format('yyyy/MM/dd hh:mm:ss')

            // 如果拉过头，那么就强制让startTime 与 endTime 一致
            // 拉过头是因为 this.actionWidth 方法计算是异步的，而v差不多是直接响应出来的，有时候v值是新的，但是actionWidth还是久的，就导致了没能拦住
            if (this.actionWidth <= 0) {
              this.blockData[this.startTimeCol] =
                this.blockData[this.endTimeCol]
            }

            this.mousePosition.left = v
          }
          //右边移动
          else if (direction == 1) {
            //v右边拉长是增加
            if (this.mousePosition.right > v) {
              //如果是缩短，那么就可以进行width不为-1的判断了
              if (this.actionWidth <= 0) {
                return
              }
            }
            //分钟赋值后，设置成new Date
            this.blockData[this.endTimeCol] = new Date(
              endTime + v * 1000 * 60
            ).format('yyyy/MM/dd hh:mm:ss')

            if (this.actionWidth <= 0) {
              this.blockData[this.endTimeCol] =
                this.blockData[this.startTimeCol]
            }

            this.mousePosition.right = v
          }
        }

        window.onmouseup = () => {
          //执行回调，让回调的地方进行http调用
          this.$emit('moveSideChange', this.blockData)

          wordDom.onmousemove = null
          window.onmouseup = null
        }
      },
      //鼠标自由拖拽用的点下
      onMouseFreeDown(e) {
        // 右键点击的情况下，不触发下列事件
        if (e.button === 2) {
          return
        }

        this.uniqueId = 0

        const box = this.$refs.box

        //时间块的宽度
        const domWidth = parseInt(box.style.width)

        //复制出一个dom 以此为操作坐标
        const copyDom = box.cloneNode(true)

        //可滚动区域
        const wordDom = document.getElementById('contentGrid')

        const diffX = e.clientX - box.offsetLeft + this.scrollLeft

        //const diffY = e.clientY - box.offsetTop

        this.$emit('onActionBlockDown')

        let startTime = this.blockData[this.startTimeCol]

        let endTime = this.blockData[this.endTimeCol]

        // 摁下的时候 当前块数据  因为虚拟列表会把这个消化掉 所以需要破绑定一下
        const downBlockData = JSON.parse(JSON.stringify(this.blockData))

        const downRowData = JSON.parse(JSON.stringify(this.rowData))

        wordDom.onmousemove = (ee) => {
          // 只有第一次移动的时候才创建虚拟dom
          if (this.uniqueId === 0) {
            wordDom.appendChild(copyDom)
            copyDom.style.opacity = '0.5'
            this.uniqueId++
          }

          const left = ee.clientX - diffX

          const top = ee.clientY - getAbsTop(wordDom) - 20

          copyDom.style.left = left + 'px'

          copyDom.style.top = top + 'px'

          startTime = new Date(
            new Date(this.choiceTime[0]).getTime() + left * 1000 * 60
          )

          endTime = new Date(startTime.getTime() + domWidth * 1000 * 60)
        }

        window.onmouseup = () => {
          const rowData = this.ganttData.find((e) => e.id === downRowData.id)
          const blockData = rowData.timeBlock.find(
            (e) => e.id === downBlockData.id
          )

          if (this.uniqueId === 0) {
            wordDom.onmousemove = null
            window.onmouseup = null

            // 因为虚拟列表的缘故 window的up事件虽然不至于会被清除  但是 寻常emit/on 事件会失效  所以使用全局的事件总线，全局的emit/on
            EventBus.$emit('onActionBlockUp', {
              blockData,
              rowData,
            })

            return
          }

          wordDom.removeChild(copyDom)

          this.blockData[this.startTimeCol] = startTime.format(
            'yyyy/MM/dd hh:mm:ss'
          )

          this.blockData[this.endTimeCol] = endTime.format(
            'yyyy/MM/dd hh:mm:ss'
          )

          // 因为虚拟列表的缘故 window的up事件虽然不至于会被清除  但是 寻常emit/on 事件会失效  所以使用全局的事件总线，全局的emit/on
          EventBus.$emit('onActionBlockUp', {
            blockData,
            rowData,
          })

          wordDom.onmousemove = null
          window.onmouseup = null
        }
      },
    },
  }
</script>

<style scoped lang="scss">
  .action-block {
    position: absolute;
    height: 40px;
    min-height: 40px;
    max-height: 40px;
    background-color: #ffedb3;
    box-sizing: border-box;
    border: 1px solid gold;

    z-index: 3;
    // border-radius: 4px;

    .action-box {
      height: 100%;
      display: flex;
      justify-content: space-between;
      .action-content {
        flex: 1;

        white-space: nowrap; /* 不换行 */
        overflow: hidden; /* 隐藏溢出文本 */
        text-overflow: ellipsis; /* 使用省略号代替无法显示的部分 */
      }
      .action {
        box-sizing: border-box;
        cursor: pointer;
        padding: 0 5px;
        opacity: 0;
        background-color: rgba(255, 255, 255, 0.5);
        &:hover {
          opacity: 1;
        }
      }
    }
  }

  .action-block:first-child {
    // background-color: red;
    box-sizing: border-box;
  }
  .action-block:nth-child(2) {
    // background-color: thistle;
    box-sizing: border-box;
  }
</style>
